package FlexTrade;

import java.io.Serializable;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Hashtable;

import net.jini.config.Configuration;
import net.jini.config.ConfigurationException;
import net.jini.config.ConfigurationProvider;
import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.LookupDiscovery;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.lease.LeaseRenewalManager;
import net.jini.lookup.ServiceDiscoveryManager;
import net.jini.lookup.entry.Name;
import net.jini.security.BasicProxyPreparer;
import net.jini.security.ProxyPreparer;
import common_classes.AuctionPrimitiveData;
import common_classes.AuctionStates;
import common_classes.BidPriceData;
import common_classes.IAuction;
import common_classes.IAuthenticate;
import common_classes.IMarketService;
import common_classes.WSEvent;

public class WSAdaptor implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -835526660346393541L;
	private Configuration config;
	private ProxyPreparer preparer = null;
	
	public WSAdaptor() {
		// TODO Auto-generated constructor stub
		try {
			config = ConfigurationProvider.getInstance(new String[] {"/home/hieuht/Eclipse/workspaceJEE/FlexTrade/src/FlexTrade/configFile.config"});
		} catch (Exception e) {
			// TODO Auto-generated catch block
			preparer = new BasicProxyPreparer();
			e.printStackTrace();
		}

	}
	
	public WSEvent[] pullWSEvents(String _uniqueAuctionID, String _customerID) {
		setSecurityPolicy();
		IAuction auction = lookUpAuction(_uniqueAuctionID);
		if (auction == null) return null;
		
		WSEvent[] eventList = null;

		if (auction != null) {
			ArrayList<WSEvent> temp = null;
			try {
				temp = auction.pullWSEventsFromAuction(_customerID);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (temp != null) {
				eventList = new WSEvent[temp.size()];
				return temp.toArray(eventList);
			}
		}
		return null;
	}

	
	public boolean receiveNewAuctionRequestFromProvider(AuctionPrimitiveData  auctionPrimitiveData) {
		IMarketService market = lookUpMarketService();
		if (market == null) {
			return false;
		} else {
			try {
				return market.receiveNewAuctionRequestFromProvider(auctionPrimitiveData, null);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}

	//FlexTrade receive new bid for this auction (English/Vickrey) 
	public boolean receiveBidPriceFromCustomer(String _uniqueAuctionID, BidPriceData _bidPriceData) {
		IAuction auction = lookUpAuction(_uniqueAuctionID);
		if (auction != null) {
			try {
				return auction.receiveBidPriceFromCustomer(_bidPriceData);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
		
	//FlexTrade receive offer acceptance from customer (Dutch Auction)
	public boolean receivePriceAcceptanceFromCustomer(String _uniqueAuctionID, BidPriceData _bidPriceData) {
		IAuction auction = lookUpAuction(_uniqueAuctionID);
		if (auction != null) {
			try {
				return auction.receivePriceAcceptanceFromCustomer(_bidPriceData);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
		
	//FlexTrade receive new offer from Provider (Dutch)
	public boolean receiveNewAcceptablePriceFromProvider(String _uniqueAuctionID,float newAcceptablePrice) {
		IAuction auction = lookUpAuction(_uniqueAuctionID);
		if (auction != null) {
			try {
				return auction.receiveNewAcceptablePriceFromProvider(newAcceptablePrice);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
	
	public AuctionPrimitiveData[] getCurrentActiveAuctions() {
		setSecurityPolicy();
		IMarketService market = lookUpMarketService();
		if (market == null) {
			return null;
		}
		Hashtable<String, AuctionPrimitiveData> list = null;
		try {
			list = market.getCurrentActiveAuctions();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (list != null) {
			AuctionPrimitiveData[] auctionList = new AuctionPrimitiveData[list.size()];
			return list.values().toArray(auctionList);
		}
		return null; 
	}
	
	public AuctionStates getAuctionState(String _uniqueAuctionID) {
		setSecurityPolicy();
		IAuction auction = lookUpAuction(_uniqueAuctionID);
		if (auction != null) {
			try {
				return auction.getCurrentAuctionStates();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}
	
	public AuctionPrimitiveData getAuctionPrimitiveData(String _uniqueAuctionID) {
		setSecurityPolicy();
		IAuction auction = lookUpAuction(_uniqueAuctionID);
		if (auction != null) {
			try {
				return auction.getAuctionPrimitiveData();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}
	
	public boolean customerJoinAuction(String _uniqueAuctionID, String _customerID) {
		setSecurityPolicy();
		IAuction auction = lookUpAuction(_uniqueAuctionID);
		if (auction != null) {
			try {
				auction.customerJoinAuction(_customerID);
				return true;
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
	
	
	public boolean authenticateCustomer(String username, String password) {
		IAuthenticate authenticate = lookUpAuthentication();
		if (authenticate != null) {
			try {
				return authenticate.authenticateCustomer(username, password);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
	
	public boolean authenticateProvider(String username, String password) {
		IAuthenticate authenticate = lookUpAuthentication();
		if (authenticate != null) {
			try {
				return authenticate.authenticateProvider(username, password);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
	
	public boolean addCustomerAccount(String username, String password) {
		IAuthenticate authenticate = lookUpAuthentication();
		if (authenticate != null) {
			try {
				return authenticate.addCustomerAccount(username, password);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
	
	public boolean addProviderAccount(String username, String password) {
		IAuthenticate authenticate = lookUpAuthentication();
		if (authenticate != null) {
			try {
				return authenticate.addProviderAccount(username, password);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
	
	public boolean paymentTransfer(String _uniqueAuctionID, float amount, 
									 String customerID, String providerID) {
		IAuction auction = lookUpAuction(_uniqueAuctionID);
		if (auction != null) {
			try {
				return auction.paymentTransfer(amount, customerID, providerID);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
	
	private IMarketService lookUpMarketService() {
		setSecurityPolicy();
		ServiceDiscoveryManager clientMgr = null;
		try {
			LookupDiscoveryManager mgr = new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
																	null, // unicast locators
																	null); // DiscoveryListener
			clientMgr = new ServiceDiscoveryManager(mgr, new LeaseRenewalManager());
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}
		//Create template to find FlexTrade service by name		
		Entry[] serverAttributes = new Entry[1];
	    serverAttributes[0] = new Name (IAuction.MARKET_SERVICE_NAME);
	    ServiceTemplate template = 
	    		  new ServiceTemplate (null, null, serverAttributes);

		ServiceItem item = null;
		// Try to find the service, blocking until timeout if necessary
		try {
			item = clientMgr.lookup(template,
										null, // no filter
										10000); // timeout
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}
		if (item == null) {
			System.out.println("No market service");
			return null;
		}
		// Get the service
		IMarketService t_market = (IMarketService) item.service;
		if (t_market != null) {
			try {
				preparer = (ProxyPreparer) config.getEntry("ProxyPreparer", "preparer", ProxyPreparer.class);
				t_market = (IMarketService) preparer.prepareProxy(t_market);
				return t_market;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}
	
	private IAuction lookUpAuction(String _uniqueAuctionID) {
		setSecurityPolicy();
		ServiceDiscoveryManager clientMgr = null;
		try {
			LookupDiscoveryManager mgr = new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
																	null, // unicast locators
																	null); // DiscoveryListener
			clientMgr = new ServiceDiscoveryManager(mgr, new LeaseRenewalManager());
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}
		//Create template to find FlexTrade service by name		
		Entry[] serverAttributes = new Entry[1];
	    serverAttributes[0] = new Name (_uniqueAuctionID);
	    ServiceTemplate template = 
	    		  new ServiceTemplate (null, null, serverAttributes);

		ServiceItem item = null;
		// Try to find the service, blocking until timeout if necessary
		try {
			item = clientMgr.lookup(template,
										null, // no filter
										10000); // timeout
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}
		if (item == null) {
			System.out.println("No auction service.");
			return null;
		}
		// Get the service
		IAuction t_auction = (IAuction) item.service;
		if (t_auction != null) {
			try {
				preparer = (ProxyPreparer) config.getEntry("ProxyPreparer", "preparer", ProxyPreparer.class);
				t_auction = (IAuction) preparer.prepareProxy(t_auction);
				return t_auction;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}
	
	private IAuthenticate lookUpAuthentication() {
		setSecurityPolicy();
		ServiceDiscoveryManager clientMgr = null;
		try {
			LookupDiscoveryManager mgr = new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
																	null, // unicast locators
																	null); // DiscoveryListener
			clientMgr = new ServiceDiscoveryManager(mgr, new LeaseRenewalManager());
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}
		//Create template to find FlexTrade service by name		
		Entry[] serverAttributes = new Entry[1];
	    serverAttributes[0] = new Name (IAuction.AUTHENTICATE_SERVICE_NAME);
	    ServiceTemplate template = 
	    		  new ServiceTemplate (null, null, serverAttributes);

		ServiceItem item = null;
		// Try to find the service, blocking until timeout if necessary
		try {
			item = clientMgr.lookup(template,
										null, // no filter
										10000); // timeout
		} catch(Exception e) {
			e.printStackTrace();
			return null;
		}
		if (item == null) {
			System.out.println("No authentication service found.");
			return null;
		}
		// Get the service
		IAuthenticate t_auth = (IAuthenticate) item.service;
		if (t_auth != null) {
			try {
				preparer = (ProxyPreparer) config.getEntry("ProxyPreparer", "preparer", ProxyPreparer.class);
				t_auth = (IAuthenticate) preparer.prepareProxy(t_auth);
				return t_auth;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}
	
	private void setSecurityPolicy() {
		System.setProperty("java.security.policy","/home/hieuht/Eclipse/workspaceJEE/FlexTrade/src/FlexTrade/policy.txt");
		System.setSecurityManager(new RMISecurityManager());
		System.setProperty("java.rmi.server.codebase", "http://localhost:9000/");
	}
}
